/*总结
1 首先创建一个库
2 根据字体文件得到face object
3 设置字体大小及第一个坐标值 
4 加载face得到字体的glyph及buffer
5 显示 （每次显示一个字符都是根据前一个字符的glyph得到下一个字符坐标的原点值，这样方便显示）
*/
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <wchar.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#define DBG_PRINTF printf
static FT_Library g_tLibrary;
static FT_Face g_tFace;
static FT_GlyphSlot g_tSlot;
static unsigned char *filename=NULL;
 
int fd_fb;
struct fb_var_screeninfo var;	/* Current var */
struct fb_fix_screeninfo fix;	/* Current fix */
int screen_size;
unsigned char *fbmem;
unsigned int line_width;
unsigned int pixel_width;
 
 
typedef struct FontBitMap {
	int iXLeft;
	int iYTop;
	int iXMax;
	int iYMax;
	int iBpp;
	int iPitch;   /* 对于单色位图, 两行象素之间的跨度 */
	int iCurOriginX;
	int iCurOriginY;
	int iNextOriginX;
	int iNextOriginY;
	unsigned char *pucBuffer;
}T_FontBitMap, *PT_FontBitMap;
 
static int FreeTypeFontInit(char *pcFontFile, unsigned int dwFontSize);
static int FreeTypeGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap);
/* color : 0x00RRGGBB */
void lcd_put_pixel(int x, int y, unsigned int color)
{
	unsigned char *pen_8 = fbmem+y*line_width+x*pixel_width;
	unsigned short *pen_16;	
	unsigned int *pen_32;	
 
	unsigned int red, green, blue;	
 
	pen_16 = (unsigned short *)pen_8;
	pen_32 = (unsigned int *)pen_8;
  //  printf("pen_8=%d\n",pen_8);
  // printf("var.bits_per_pixel=%d\n",var.bits_per_pixel);
	switch (var.bits_per_pixel)
	{
		case 8:
		{
			*pen_8 = color;
			break;
		}
		case 16:
		{
			/* 565 */
			red   = (color >> 16) & 0xff;
			green = (color >> 8) & 0xff;
			blue  = (color >> 0) & 0xff;
			color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
			*pen_16 = color;
			break;
		}
		case 32:
		{
			*pen_32 = color;
			break;
		}
		default:
		{
			printf("can't surport %dbpp\n", var.bits_per_pixel);
			break;
		}
	}
}
 
static int FreeTypeGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
{
	int iError;
	int iPenX = ptFontBitMap->iCurOriginX;
	int iPenY = ptFontBitMap->iCurOriginY;
 
	/* load glyph image into the slot (erase previous one) */
	//iError = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER );
	iError = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
 
	//DBG_PRINTF("iPenX = %d, iPenY = %d, bitmap_left = %d, bitmap_top = %d, width = %d, rows = %d\n", iPenX, iPenY, g_tSlot->bitmap_left, g_tSlot->bitmap_top, g_tSlot->bitmap.width, g_tSlot->bitmap.rows);
	ptFontBitMap->iXLeft    = iPenX + g_tSlot->bitmap_left;
	ptFontBitMap->iYTop     = iPenY - g_tSlot->bitmap_top;
	ptFontBitMap->iXMax     = ptFontBitMap->iXLeft + g_tSlot->bitmap.width;
	ptFontBitMap->iYMax     = ptFontBitMap->iYTop  + g_tSlot->bitmap.rows;
	ptFontBitMap->iBpp      = 1;
	ptFontBitMap->iPitch    = g_tSlot->bitmap.pitch;
	ptFontBitMap->pucBuffer = g_tSlot->bitmap.buffer;
	
	ptFontBitMap->iNextOriginX = iPenX + g_tSlot->advance.x / 64;
	ptFontBitMap->iNextOriginY = iPenY;
 
	return 0;
}
 
int ShowOneFont(PT_FontBitMap ptFontBitMap)
{
	int x;
	int y;
	unsigned char ucByte = 0;
	int i = 0;
	int bit;
	if (ptFontBitMap->iBpp == 1)
	{
		for (y = ptFontBitMap->iYTop; y < ptFontBitMap->iYMax; y++)
		{
			i = (y - ptFontBitMap->iYTop) * ptFontBitMap->iPitch;
			for (x = ptFontBitMap->iXLeft, bit = 7; x < ptFontBitMap->iXMax; x++)
			{
				if (bit == 7)
				{
					ucByte = ptFontBitMap->pucBuffer[i++];
				}
				
				if (ucByte & (1<<bit))
				{
					lcd_put_pixel(x,y, 0xffffffff);
					//g_ptDispOpr->ShowPixel(x, y, COLOR_FOREGROUND);
				}
				else
				{
					/* 使用背景色, 不用描画 */
					// g_ptDispOpr->ShowPixel(x, y, 0); /* 黑 */
				}
				bit--;
				if (bit == -1)
				{
					bit = 7;
				}
			}
		}
	}
	else
	{
		DBG_PRINTF("ShowOneFont error, can't support %d bpp\n", ptFontBitMap->iBpp);
		return -1;
	}
	return 0;
}
static int FreeTypeFontInit(char *pcFontFile, unsigned int dwFontSize)
{
	int iError;
	/* 显示矢量字体 */
	iError = FT_Init_FreeType(&g_tLibrary );			   /* 初始化库 */
    iError = FT_New_Face(g_tLibrary, pcFontFile, 0, &g_tFace); /*根据字体文件得到face */
	g_tSlot = g_tFace->glyph;
	iError = FT_Set_Pixel_Sizes(g_tFace, dwFontSize, 0); /* 设置字体大小*/
	return 0;
}
 
  int main(int argc, char **argv)
{
		unsigned char str[] = "中";
		int i;
		int n;
		int error;
		filename=argv[1];
		T_FontBitMap tFontBitMap;
		
		wchar_t *chinese_str1 = L"XGZX 工作室"; //L表示从ansi码转成unicode字符集
		wchar_t *chinese_str2 = L"还在";
 
		tFontBitMap.iCurOriginX = 250;
		tFontBitMap.iCurOriginY = 250;
		fd_fb = open("/dev/fb0", O_RDWR);
		if (fd_fb < 0)
		{
			printf("can't open /dev/fb0\n");
			return -1;
		}
		if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
		{
			printf("can't get var\n");
			return -1;
		}
		if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix))
		{
			printf("can't get fix\n");
			return -1;
		}
		line_width  = var.xres * var.bits_per_pixel / 8;
		printf("line_width=%d\n",line_width);
		pixel_width = var.bits_per_pixel / 8;
		printf("pixel_width=%d\n",pixel_width);
		screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
		printf("screen_size=%d\n",screen_size);
		fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
		/* 清屏: 全部设为黑色 */
		memset(fbmem, 0, screen_size);	

		
		error=FreeTypeFontInit(filename,50);
        
		for ( n = 0; n < wcslen(chinese_str1); n++ )
		{
			FreeTypeGetFontBitmap(chinese_str1[n],&tFontBitMap);						
			ShowOneFont(&tFontBitMap);
			tFontBitMap.iCurOriginX = tFontBitMap.iNextOriginX;
			tFontBitMap.iCurOriginY = tFontBitMap.iNextOriginY;						
		}
	
 
		return 0;	
}

  

